package cn.me.alphamq.nameserver.task.cluster;

import cn.me.alphamq.nameserver.cache.Container;
import cn.me.alphamq.nameserver.config.cluster.ChainReplicationProperties;
import cn.me.alphamq.nameserver.config.cluster.MasterSlaveReplicationProperties;
import cn.me.alphamq.nameserver.enumeration.ReplicationModeEnum;
import cn.me.alphamq.nameserver.enumeration.ReplicationRoleEnum;
import cn.me.alphamq.nameserver.task.cluster.chain.NodeSendReplicationMsgTask;
import cn.me.alphamq.nameserver.task.cluster.masterslave.MasterSendReplicationMsgTask;
import cn.me.alphamq.nameserver.task.cluster.masterslave.SlaveStartReplicationTask;

/**
 * 复制任务的抽象父类
 *
 * @author f
 */
public abstract class ReplicationTask {

    /**
     * 开启复制任务
     */
    public static void startTask() {
        ReplicationModeEnum replicationModeEnum = Container.getClusterProperties().getReplicationModeEnum();

        // 单机模式不需要开启复制任务，直接返回
        if (ReplicationModeEnum.STANDALONE == replicationModeEnum) {
            return;
        }

        if (ReplicationModeEnum.MASTER_SLAVE == replicationModeEnum) {
            startMasterSlaveTask();
        } else if (ReplicationModeEnum.CHAIN == replicationModeEnum) {
            startChainTask();
        }
    }

    // 开启链式复制的任务
    private static void startChainTask() {
        ChainReplicationProperties replicationProperties =
                Container.getClusterProperties().getChainReplicationProperties();

        ReplicationTask replicationTask;
        String threadName;

        // 根据不同角色获取不同的任务
        ReplicationRoleEnum role = replicationProperties.getRole();
        if (ReplicationRoleEnum.NODE == role) {
            // 如果是非尾节点，则开启给下一个节点发送复制消息的任务
            replicationTask = new NodeSendReplicationMsgTask();
            threadName = "send-replication-msg-task-thread";
        } else if (ReplicationRoleEnum.TAIL == role) {
            // 如果是尾节点，则不用开启
            return;
        } else {
            throw new RuntimeException("invalid replication role: " + role.getCode());
        }

        // 在子线程中做复制任务
        doTaskInSubThread(replicationTask, threadName);
    }

    // 开启主从复制的任务
    private static void startMasterSlaveTask() {
        MasterSlaveReplicationProperties replicationProperties =
                Container.getClusterProperties().getMasterReplicationProperties();

        ReplicationTask replicationTask;
        String threadName;

        // 根据不同角色获取不同的任务
        ReplicationRoleEnum role = replicationProperties.getRole();
        if (ReplicationRoleEnum.MASTER == role) {
            // 如果是主节点，则开启复制
            replicationTask = new MasterSendReplicationMsgTask();
            threadName = "send-replication-msg-task-thread";
        } else if (ReplicationRoleEnum.SLAVE == role) {
            // 如果是从节点，则开启心跳任务，发送心跳包给主节点
            replicationTask = new SlaveStartReplicationTask();
            threadName = "send-replication-heart-beat-task-thread";
        } else {
            throw new RuntimeException("invalid replication role: " + role.getCode());
        }

        // 在子线程中做复制任务
        doTaskInSubThread(replicationTask, threadName);
    }

    // 在子线程中做复制任务
    private static void doTaskInSubThread(ReplicationTask replicationTask, String threadName) {
        new Thread(replicationTask::replicationTask, threadName).start();
    }

    /**
     * 复制任务
     */
    protected abstract void replicationTask();

}
